//SPDX-FileCopyrightText: Copyright 2025-2025 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

use prost::Message;
use prost_types::FileDescriptorSet;
use quote::{format_ident, quote};
use std::fs::{self, File, OpenOptions};
use std::io::Write;
use std::path::Path;
use std::path::PathBuf;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let out_dir = PathBuf::from("src");
    tonic_build::configure()
        .build_server(false)
        .type_attribute(".", "#[derive(serde::Serialize,serde::Deserialize)]")
        .out_dir("src")
        .compile_well_known_types(true)
        .file_descriptor_set_path("src/fd.bin")
        .compile(
            &[
                "auth_secret_api.proto",
                "admin_api.proto",
                "config_api.proto",
                "image_api.proto",
                "image_group_api.proto",
                "member_api.proto",
                "watch_api.proto"
            ],
            &["proto"],
        )
        .unwrap();
    let fd_data = fs::read("src/fd.bin").unwrap();
    let fd = FileDescriptorSet::decode(&fd_data[..]).unwrap();
    generate_extras(&out_dir, &fd);
    Ok(())
}

fn generate_extras(out_dir: &Path, file_descriptor_set: &FileDescriptorSet) {
    for fd in &file_descriptor_set.file {
        let package = match fd.package {
            Some(ref pkg) => pkg,
            None => continue,
        };

        if package.starts_with("google.") {
            continue;
        }

        let gen_path = out_dir.join(format!("{}.rs", package));
        let mut gen_file = OpenOptions::new().append(true).open(gen_path).unwrap();

        for msg in &fd.message_type {
            let name = match msg.name {
                Some(ref name) => name,
                None => continue,
            };

            let type_url = format!("type.googleapis.com/{}.{}", package, name);

            gen_type_url(&mut gen_file, &type_url, name);
        }
    }
}

fn gen_type_url(gen_file: &mut File, type_url: &str, type_name: &str) {
    let type_name = format_ident!("{}", type_name);

    let tokens = quote! {
        impl crate::TypeUrl for #type_name {
            fn type_url() -> &'static str {
                #type_url
            }
        }
    };

    writeln!(gen_file).unwrap();
    writeln!(gen_file, "{}", &tokens).unwrap();
}
